package com.rankeiot.core.util;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.ShearCaptcha;
import cn.hutool.captcha.generator.CodeGenerator;
import com.rankeiot.core.Context;
import com.rankeiot.core.exception.BusinessException;
import jakarta.servlet.http.HttpServletResponse;
import org.sagacity.sqltoy.utils.IdUtil;
import org.sagacity.sqltoy.utils.StringUtil;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;


import java.util.*;

@SuppressWarnings("AlibabaConstantFieldShouldBeUpperCase")
public class Captcha {


    public static final String captchaCookieName = "_captcha";
    public static long expiration = 300; //过期时间5分钟

    static {
        System.setProperty("java.awt.headless", "true");
    }

    //    private static Cache<String,String> captchaCache= Caffeine.newBuilder()
//            .expireAfterWrite(expiration, TimeUnit.SECONDS).build();
    private static Cache _captchaCache;
    private synchronized static Cache getCaptchaCache(){
        if(_captchaCache==null){
            CacheManager cm= Context.getBean(CacheManager.class);
            _captchaCache = cm.getCache("CaptchaCache");
        }
        return _captchaCache;
    }
    private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");


    private static class MathCaptchaGenerator implements CodeGenerator{
        Integer result = 0;
        @Override
        public String generate() {

            Random random = new Random();
            int x = random.nextInt(10);
            int y = random.nextInt(10);
            StringBuilder suChinese = new StringBuilder();
            int randomoperands = random.nextInt(3);
            if (randomoperands == 0)
            {
                result = x * y;
                suChinese.append(CNUMBERS[x]);
                suChinese.append("×");
                suChinese.append(CNUMBERS[y]);
            }
            else if (randomoperands == 1)
            {
                if ((x != 0) && y % x == 0)
                {
                    result = y / x;
                    suChinese.append(CNUMBERS[y]);
                    suChinese.append("÷");
                    suChinese.append(CNUMBERS[x]);
                }
                else
                {
                    result = x + y;
                    suChinese.append(CNUMBERS[x]);
                    suChinese.append("+");
                    suChinese.append(CNUMBERS[y]);
                }
            }
            else
            {
                if (x >= y)
                {
                    result = x - y;
                    suChinese.append(CNUMBERS[x]);
                    suChinese.append("-");
                    suChinese.append(CNUMBERS[y]);
                }
                else
                {
                    result = y - x;
                    suChinese.append(CNUMBERS[y]);
                    suChinese.append("-");
                    suChinese.append(CNUMBERS[x]);
                }
            }
            return suChinese.append("=?").toString();
        }
        public Integer getResult(){
            return result;
        }
        @Override
        public boolean verify(String s, String s1) {
            return false;
        }
    }
    /**
     * 输出验证码
     *
     * @param oldCaptcha
     */
    public static ResponseEntity<StreamingResponseBody> captcha(String oldCaptcha) {
        ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(160, 60, 6, 4);
        MathCaptchaGenerator mg=new MathCaptchaGenerator();
        captcha.setGenerator(mg);
        captcha.createCode();
//        captcha.setOnlyNumber(onlyNumber);
       Cache captchaCache= getCaptchaCache();
        //清除旧的验证码
       // String old =request.getNativeRequest(HttpServletRequest.class).getCookies()// ctx.cookie(captchaCookieName);
        if (StringUtil.isNotBlank(oldCaptcha)) {
            //过期 captchaCache.invalidate(old);
            captchaCache.evict(oldCaptcha);//.remove(old);
        }
        String cptId = IdUtil.getUUID();
        captchaCache.put(cptId, mg.getResult()+"");
//        HttpServletResponse response = request.getNativeResponse(HttpServletResponse.class);
//        response.setHeader("Set-Cookie",captchaCookieName+"="+cptId+"; Path=/; HttpOnly; Max-Age="+expiration+";");
//         try {
//             response.setContentType("image/png");
//            response.setHeader("Cache-Control", "no-cache");
//            captcha.write(response.getOutputStream());
//           // captcha.out(ctx.outputStream());
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
         return ResponseEntity.ok()
                 .contentType(MediaType.IMAGE_PNG)
                 .header("Cache-Control","no-cache")
                  . header("Set-Cookie",captchaCookieName+"="+cptId+"; Path=/; HttpOnly; Max-Age="+expiration+"; SameSite=Lax;")
                 .body(out -> {
                     captcha.write(out);
                 });
    }
    public static Map<String,Object> captchaAjax(){
        ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(160, 60, 6, 4);
        MathCaptchaGenerator mg=new MathCaptchaGenerator();
        captcha.setGenerator(mg);
        captcha.createCode();
        String cptId = IdUtil.getUUID();
        Cache captchaCache= getCaptchaCache();
        captchaCache.put(cptId, mg.getResult()+"");
        Map<String,Object> data=new HashMap<>();
        data.put("success",true);
        data.put("data", captcha.getImageBase64Data());
        data.put("captchaId",cptId);
        return data;
    }
    public static boolean  verify(String captcha,String cpId){
        if (StringUtil.isBlank(captcha)) {
            return false;
        }
        if (StringUtil.isBlank(cpId)) {
            return false;
        }
        Cache captchaCache= getCaptchaCache();
        String cacheCaptcha = (String)captchaCache.get(cpId).get();//captchaCache.getIfPresent(cpId);
        if (StringUtil.isNotBlank(cacheCaptcha)) {
            captchaCache.evict(cpId);
        }
        try{
            int r=Integer.valueOf(captcha);
            return Objects.equals(r, Integer.valueOf(cacheCaptcha));
        }catch (Exception e){
            throw new BusinessException("验证码错误");
        }
    }
    /**
     * 验证验证码
     * @param request
     * @param captcha
     * @param captchaId
     * @return
     */
    public static boolean verify(ServletRequestAttributes request, String captcha, String captchaId) {
        if (StringUtil.isBlank(captcha)) {
            return false;
        }
        if (StringUtil.isBlank(captchaId)) {
            return false;
        }
        Cache captchaCache= getCaptchaCache();
       Cache.ValueWrapper cv= captchaCache.get(captchaId);
       if(cv==null){
           return false;
       }
        String cacheCaptcha = (String)cv.get();//captchaCache.getIfPresent(cpId);
        if (StringUtil.isNotBlank(cacheCaptcha)) {
            HttpServletResponse response = request.getResponse();
            response.setHeader("Set-Cookie",captchaCookieName+"= ; Path=/; HttpOnly; Max-Age=0;");
            captchaCache.evict(captchaId);
        }
        try{
            int r=Integer.valueOf(captcha);
            return Objects.equals(r, Integer.valueOf(cacheCaptcha));
        }catch (Exception e){
            throw new BusinessException("验证码错误");
        }
    }
    public static String phoneCode(String phone){
        Cache captchaCache= getCaptchaCache();
        String code=generateVerificationCode();
        captchaCache.put("phone_"+phone,code);
        return code;
    }
    public static boolean verifyPhoneCode(String phone,String code){
        Cache captchaCache= getCaptchaCache();
        String key="phone_"+phone;
        Cache.ValueWrapper cv= captchaCache.get(key);
        if(cv==null){
            return false;
        }
        String cacheCaptcha = (String)cv.get();//captchaCache.getIfPresent(cpId);
        boolean isOk=Objects.equals(cacheCaptcha, code)&&code!=null;
        if (isOk) {
           captchaCache.evict(key);
        }
        return isOk;
    }
    private static String generateVerificationCode() {
        Random random = new Random();
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            code.append(random.nextInt(10));
        }
        return code.toString();
    }

}
